package barcode

import (
	"encoding/binary"
	"fmt"
	
	"inkjet168x-sdk-go/sdk/protocol/common"
)

// Protocol 条码协议实现
type Protocol struct {
	// 协议头部
	StartBytes   [4]uint8  // 起始位: 0x5A 0x4B 0x43 0x54
	Sequence     uint16    // 序列号
	PacketType   uint8     // 数据包类型: 0x04
	PacketLength uint32    // 数据包长度
	
	// 条码内容
	Text         [256]byte // 条码内容，不足256位补零，超过256位不支持
	
	// 条码设置
	BarcodeType  uint32    // 条码类型
	Position     common.Position // 位置信息
	Size         common.Size     // 尺寸信息
	TextDisplay  uint32    // 文本显示，0: 不显示，其他值: 显示
	TextHeight   uint32    // 文本高度，范围: 0-999999
	Reserved     [4]uint8  // 保留字节
	Checksum     uint16    // CRC16校验和
	StopBytes    [2]uint8  // 停止位: 0x0D 0x0A
}

// Type 条码类型枚举
type Type uint32

const (
	TypeQRCode     Type = 0x00 // QRCODE
	TypePDF417     Type = 0x01 // PDF417
	TypeDataMatrix Type = 0x02 // DATAMATRIX
	TypeDTMXGS1    Type = 0x03 // DTMX-GS1
	TypeUPCA       Type = 0x04 // UPCA
	TypeUPCE       Type = 0x05 // UPCE
	TypeEAN13      Type = 0x06 // EAN13
	TypeEAN8       Type = 0x07 // EAN8
	TypeINT25      Type = 0x08 // INT25
	TypeCODE39     Type = 0x09 // CODE39
	TypeCODE128    Type = 0x0A // CODE128
	TypeEAN128     Type = 0x0B // EAN128
	TypeITF14      Type = 0x0C // ITF14
)

// String 返回条码类型的字符串表示
func (bt Type) String() string {
	switch bt {
	case TypeQRCode:
		return "QRCODE"
	case TypePDF417:
		return "PDF417"
	case TypeDataMatrix:
		return "DATAMATRIX"
	case TypeDTMXGS1:
		return "DTMX-GS1"
	case TypeUPCA:
		return "UPCA"
	case TypeUPCE:
		return "UPCE"
	case TypeEAN13:
		return "EAN13"
	case TypeEAN8:
		return "EAN8"
	case TypeINT25:
		return "INT25"
	case TypeCODE39:
		return "CODE39"
	case TypeCODE128:
		return "CODE128"
	case TypeEAN128:
		return "EAN128"
	case TypeITF14:
		return "ITF14"
	default:
		return fmt.Sprintf("未知条码类型(%d)", uint32(bt))
	}
}

// NewProtocol 创建新的条码协议实例
func NewProtocol() common.Protocol {
	return &Protocol{
		StartBytes:  [4]uint8{common.StartByte1, common.StartByte2, common.StartByte3, common.StartByte4},
		PacketType:  uint8(common.ProtocolTypeBarcode),
		StopBytes:   [2]uint8{common.StopByte1, common.StopByte2},
		BarcodeType: uint32(TypeQRCode), // 默认二维码
		TextDisplay: 1,                  // 默认显示文本
		TextHeight:  12,                 // 默认文本高度
	}
}

// GetType 获取协议类型
func (bp *Protocol) GetType() common.ProtocolType {
	return common.ProtocolTypeBarcode
}

// SetSequence 设置序列号
func (bp *Protocol) SetSequence(seq uint16) {
	bp.Sequence = seq
}

// GetSequence 获取序列号
func (bp *Protocol) GetSequence() uint16 {
	return bp.Sequence
}

// Marshal 序列化为字节数组
func (bp *Protocol) Marshal() ([]byte, error) {
	// 计算数据包长度 (不包括起始位、序列号、包类型、包长度字段本身)
	bp.PacketLength = uint32(292) // 条码内容+条码设置+保留+校验+停止位
	
	// 计算需要的总字节数(固定值)
	totalSize := 307
	data := make([]byte, totalSize)
	
	offset := 0
	
	// 起始位
	copy(data[offset:], bp.StartBytes[:])
	offset += 4
	
	// 序列号 (大端序)
	binary.BigEndian.PutUint16(data[offset:], bp.Sequence)
	offset += 2
	
	// 数据包类型
	data[offset] = bp.PacketType
	offset += 1
	
	// 数据包长度 (小端序)
	binary.LittleEndian.PutUint32(data[offset:], bp.PacketLength)
	offset += 4
	
	// 条码内容
	copy(data[offset:], bp.Text[:])
	offset += 256
	
	// 条码设置 (小端序)
	binary.LittleEndian.PutUint32(data[offset:], bp.BarcodeType)
	offset += 4

	// 保留字节
	copy(data[offset:], bp.Reserved[:])
	offset += 4

	binary.LittleEndian.PutUint32(data[offset:], bp.Position.X)
	offset += 4
	binary.LittleEndian.PutUint32(data[offset:], bp.Position.Y)
	offset += 4
	binary.LittleEndian.PutUint32(data[offset:], bp.Size.Width)
	offset += 4
	binary.LittleEndian.PutUint32(data[offset:], bp.Size.Height)
	offset += 4
	binary.LittleEndian.PutUint32(data[offset:], bp.TextDisplay)
	offset += 4
	binary.LittleEndian.PutUint32(data[offset:], bp.TextHeight)
	offset += 4
	
	// 保留字节
	copy(data[offset:], bp.Reserved[:])
	offset += 4
	
	// 计算校验和 (仅校验数据包部分，从第11字节开始)
	bp.Checksum = common.CalculateChecksum(data[11:offset])
	binary.LittleEndian.PutUint16(data[offset:], bp.Checksum)
	offset += 2
	
	// 停止位
	copy(data[offset:], bp.StopBytes[:])
	
	return data, nil
}

// Unmarshal 从字节数组反序列化
func (bp *Protocol) Unmarshal(data []byte) error {
	if len(data) < 303 { // 最小包长度
		return fmt.Errorf("数据包太短: %d 字节", len(data))
	}
	
	offset := 0
	
	// 起始位
	copy(bp.StartBytes[:], data[offset:offset+4])
	offset += 4
	
	// 序列号
	bp.Sequence = binary.BigEndian.Uint16(data[offset:])
	offset += 2
	
	// 数据包类型
	bp.PacketType = data[offset]
	offset += 1
	
	// 数据包长度
	bp.PacketLength = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	
	// 条码内容
	copy(bp.Text[:], data[offset:offset+256])
	offset += 256
	
	// 条码设置
	bp.BarcodeType = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	bp.Position.X = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	bp.Position.Y = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	bp.Size.Width = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	bp.Size.Height = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	bp.TextDisplay = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	bp.TextHeight = binary.LittleEndian.Uint32(data[offset:])
	offset += 4
	
	// 保留字节
	copy(bp.Reserved[:], data[offset:offset+4])
	offset += 4
	
	// 校验和
	bp.Checksum = binary.LittleEndian.Uint16(data[offset:])
	offset += 2
	
	// 停止位
	copy(bp.StopBytes[:], data[offset:offset+2])
	
	return nil
}

// Validate 验证协议参数
func (bp *Protocol) Validate() error {
	// 验证位置
	if err := common.ValidateRange(bp.Position.X, 0, 999999, "横坐标"); err != nil {
		return err
	}
	if err := common.ValidateRange(bp.Position.Y, 0, 999999, "纵坐标"); err != nil {
		return err
	}
	
	// 验证尺寸
	if err := common.ValidateRange(bp.Size.Width, 1, 999999, "条码宽度"); err != nil {
		return err
	}
	if err := common.ValidateRange(bp.Size.Height, 1, 999999, "条码高度"); err != nil {
		return err
	}
	
	// 验证文本高度
	if err := common.ValidateRange(bp.TextHeight, 0, 999999, "文本高度"); err != nil {
		return err
	}
	
	// 验证条码内容不为空
	text := bp.GetText()
	if len(text) == 0 {
		return fmt.Errorf("条码内容不能为空")
	}
	
	return nil
}

// String 返回协议的字符串表示
func (bp *Protocol) String() string {
	text := bp.GetText()
	if len(text) > 20 {
		text = text[:17] + "..."
	}
	
	barcodeType := Type(bp.BarcodeType)
	return fmt.Sprintf("BarcodeProtocol{Seq:%d Type:%s Size:%s Pos:%s Text:\"%s\"}",
		bp.Sequence, barcodeType.String(), bp.Size.String(), bp.Position.String(), text)
}

// SetText 设置条码内容
func (bp *Protocol) SetText(text string) {
	// 清空条码内容数组
	for i := range bp.Text {
		bp.Text[i] = 0
	}
	
	// 复制条码内容，最多255字节（保留一个字节作为结束符）
	textBytes := []byte(text)
	copyLen := len(textBytes)
	if copyLen > 255 {
		copyLen = 255
	}
	copy(bp.Text[:], textBytes[:copyLen])
}

// GetText 获取条码内容
func (bp *Protocol) GetText() string {
	// 找到第一个零字节的位置
	end := 256
	for i, b := range bp.Text {
		if b == 0 {
			end = i
			break
		}
	}
	return string(bp.Text[:end])
}

// SetBarcodeType 设置条码类型
func (bp *Protocol) SetBarcodeType(barcodeType Type) {
	bp.BarcodeType = uint32(barcodeType)
}

// SetPosition 设置位置
func (bp *Protocol) SetPosition(x, y uint32) {
	bp.Position.X = x
	bp.Position.Y = y
}

// SetSize 设置尺寸
func (bp *Protocol) SetSize(width, height uint32) {
	bp.Size.Width = width
	bp.Size.Height = height
}

// SetTextDisplay 设置文本显示
func (bp *Protocol) SetTextDisplay(display bool) {
	if display {
		bp.TextDisplay = 1
	} else {
		bp.TextDisplay = 0
	}
}

// SetTextHeight 设置文本高度
func (bp *Protocol) SetTextHeight(height uint32) {
	bp.TextHeight = height
}

// SetWidth 设置条码宽度
func (bp *Protocol) SetWidth(width uint32) {
	bp.Size.Width = width
}

// SetHeight 设置条码高度
func (bp *Protocol) SetHeight(height uint32) {
	bp.Size.Height = height
}

// GetBarcodeType 获取条码类型
func (bp *Protocol) GetBarcodeType() Type {
	return Type(bp.BarcodeType)
}

// GetPosition 获取位置信息
func (bp *Protocol) GetPosition() (uint32, uint32) {
	return bp.Position.X, bp.Position.Y
}

// GetSize 获取尺寸信息
func (bp *Protocol) GetSize() (uint32, uint32) {
	return bp.Size.Width, bp.Size.Height
}

// GetTextDisplay 获取文本显示设置
func (bp *Protocol) GetTextDisplay() bool {
	return bp.TextDisplay != 0
}

// GetTextHeight 获取文本高度
func (bp *Protocol) GetTextHeight() uint32 {
	return bp.TextHeight
}